# -*- coding: utf-8 -*-

"""
@name: utils
@author: Memory
@date: 2021/05/08
@document: 为服务端提供一些辅助类和辅助函数
"""

import json
import sqlite3
from random import choice
from datetime import datetime
from easydict import EasyDict
from configs import *


class Logging:
    """用来打印日志的类"""
    def __init__(self, path: Path = None):
        self.path = path
        self.output = True
        path.mkdir(parents=True, exist_ok=True)

    def print(self, *args):
        """
        打印日志，并写入到文件中。
        """
        # 构造日志格式
        datenow = datetime.now()
        now = datenow.strftime('%Y-%m-%d %H:%M:%S : ')
        log = [str(s) for s in args]
        logstr = now + ' '.join(log)
        # 打印
        print(logstr)
        if not self.path or not self.output:
            return
        # 写入到文件中
        log_file = self.path / datenow.strftime('log_%Y_%m_%d.txt')
        with open(log_file, 'a+') as f:
            f.write(logstr + '\n')


def excuteSQL(sql, value=None, db=USERDB.as_posix()):
    """
    执行一条SQL语句，如果是select，就返回查询结果，如果出错返回None。
    """
    sql = sql.upper()
    conn = sqlite3.connect(db)
    cursor = conn.cursor()
    result = []
    try:
        if value:
            cursor.execute(sql, value)
        else:
            cursor.execute(sql)
        if sql.startswith('SELECT'):
            result = cursor.fetchall()
    except:
        Logging(SERVER_LOG_PATH).print('数据库操作失败： %s' % sql)
        return None
    finally:
        cursor.close()
        conn.commit()
        conn.close()
        return result


def spilt_data(data):
    """
    用来将服务器传来的数据包分开。
    默认客户端和服务器端每次传送的数据都是
    一个标准的json字符串加上换行符，因此只要
    根据换行符进行数据分离就可以了。
    """
    jsons = []
    try:
        lines = data.decode('utf-8').split('\n')
    except:
        Logging(SERVER_LOG_PATH).print('非法内容： ', data)
        return jsons
    for line in lines:
        line = line.strip()
        if line == '':
            continue
        try:
            # 防止传来的不是json数据导致解析出错
            j = EasyDict(json.loads(line))
            jsons.append(j)
        except:
            Logging(SERVER_LOG_PATH).print('json数据解析失败，内容为： %s' % line)

    return jsons


def dict2bin(data):
    """
    将字典数据转换成字符串，然后加上一个换行符，
    再转换成二进制数据。
    """
    strdata = json.dumps(data)
    strdata = strdata + '\n'
    return strdata.encode('utf-8')


def get_user(name):
    """
    查询一个用户名的信息。
    """
    sql = 'SELECT credit, title FROM user WHERE name=?'
    value = (name,)
    result = excuteSQL(sql, value)[0]
    return {'name': name, 'credit': result[0], 'title': result[1]}


def random_chess():
    """
    随机生成一盘棋局。
    """
    CHESS_NUM = [2, 2, 4, 4, 8, 16]
    all_pos = [(i, j) for i in range(6) for j in range(6)]
    chess = [[[] for i in range(6)] for j in range(6)]
    level = 0
    for i in range(36):
        x, y = choice(all_pos)
        all_pos.remove((x, y))
        if i % 2 == 0:
            chess[x][y] = ['red', level]
        else:
            chess[x][y] = ['blue', level]

        CHESS_NUM[level] -= 1
        if CHESS_NUM[level] <= 0:
            level += 1
    return chess


def createDatabase():
    if USERDB.exists():
        return
    sql = '''
            CREATE TABLE USER
            (
            NAME VARCHAR(20) PRIMARY KEY,
            PASSWD VARCHAR(20) NOT NULL,
            CREDIT INT NOT NULL,
            TITLE VARCHAR(8)
            );
            '''
    excuteSQL(sql)
    sql = "INSERT INTO USER(NAME, PASSWD, CREDIT, TITLE) VALUES(?, ?, ?, ?)"
    excuteSQL(sql, ('xinxin', '2333', 2000, '男爵'))
    sql = "INSERT INTO USER(NAME, PASSWD, CREDIT, TITLE) VALUES(?, ?, ?, ?)"
    excuteSQL(sql, ('memory', '2333', 2000, '男爵'))
